//package authentication.config.sharding.config.jdbc.v5_0_0;
//
//import com.zaxxer.hikari.HikariDataSource;
//import org.apache.ibatis.session.SqlSessionFactory;
//import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
//import org.apache.shardingsphere.infra.config.RuleConfiguration;
//import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
//import org.apache.shardingsphere.replicaquery.api.config.ReplicaQueryRuleConfiguration;
//import org.apache.shardingsphere.replicaquery.api.config.rule.ReplicaQueryDataSourceRuleConfiguration;
//import org.apache.shardingsphere.replicaquery.spi.ReplicaLoadBalanceAlgorithm;
//import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
//import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
//import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration;
//import org.apache.shardingsphere.sharding.api.config.strategy.sharding.HintShardingStrategyConfiguration;
//import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
//import org.mybatis.spring.SqlSessionFactoryBean;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import tk.mybatis.spring.annotation.MapperScan;
//
//import javax.sql.DataSource;
//import java.sql.*;
//import java.util.*;
//import java.util.function.Function;
//
///**
// * @Author: Qiao Hang
// * @CreateDate: 2021/4/22 上午11:58
// * @UpdateDate:
// * @Description:
// */
//@Configuration
//@MapperScan(basePackages = "authentication.mappers",
//        sqlSessionFactoryRef = "sqlSessionFactory")
//public class ShardingJDBC5_0_0Adaptor {
//
//
//    /**
//     * 数据源配置，路由均路由到Master上(Master进行了分库分表)，
//     * 对Master各个节点进行DQL/DML操作时，DML操作被从节点SQL线程同步，DQL使用 Balancer 策略选择查询.
//     * @return
//     */
//    private Map<String, DataSource> dataSourceMap(){
//        // 配置真实数据源
//        Map<String, DataSource> dataSourceMap = new HashMap<>();
//
//        // 配置第 1 个数据源 dn1:3306 -> test,test2,test3
//        HikariDataSource dataSource1 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 dn0 : 118.31.13.167:3306/test");
//                return super.getConnection();
//            }
//        };
//        dataSource1.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource1.setJdbcUrl("jdbc:mysql://118.31.13.167:3306/test?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource1.setUsername("root");
//        dataSource1.setPassword("root");
//        dataSourceMap.put("dn0", dataSource1);
//
//        HikariDataSource dataSource1_1 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 dn1 : 118.31.13.167:3306/test2");
//                return super.getConnection();
//            }
//        };
//        dataSource1_1.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource1_1.setJdbcUrl("jdbc:mysql://118.31.13.167:3306/test2?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource1_1.setUsername("root");
//        dataSource1_1.setPassword("root");
//        dataSourceMap.put("dn1", dataSource1_1);
//
//        HikariDataSource dataSource1_2 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 dn2 : 118.31.13.167:3306/test3");
//                return super.getConnection();
//            }
//        };
//        dataSource1_2.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource1_2.setJdbcUrl("jdbc:mysql://118.31.13.167:3306/test3?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource1_2.setUsername("root");
//        dataSource1_2.setPassword("root");
//        dataSourceMap.put("dn2", dataSource1_2);
//
//
//
//        // 配置第 2 个数据源 dn2:3307 -> test,test2,test3
//        HikariDataSource dataSource2 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave0_test : 118.31.13.167:3307/test");
//                return super.getConnection();
//            }
//        };
//        dataSource2.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource2.setJdbcUrl("jdbc:mysql://118.31.13.167:3307/test?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource2.setUsername("root");
//        dataSource2.setPassword("root");
//        dataSourceMap.put("slave0_test", dataSource2);
//
//        HikariDataSource dataSource2_1 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave0_test2 : 118.31.13.167:3307/test2");
//                return super.getConnection();
//            }
//        };
//        dataSource2_1.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource2_1.setJdbcUrl("jdbc:mysql://118.31.13.167:3307/test2?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource2_1.setUsername("root");
//        dataSource2_1.setPassword("root");
//        dataSourceMap.put("slave0_test2", dataSource2_1);
//
//        HikariDataSource dataSource2_2 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave0_test3 : 118.31.13.167:3307/test3");
//                return super.getConnection();
//            }
//        };
//        dataSource2_2.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource2_2.setJdbcUrl("jdbc:mysql://118.31.13.167:3307/test3?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource2_2.setUsername("root");
//        dataSource2_2.setPassword("root");
//        dataSourceMap.put("slave0_test3", dataSource2_2);
//
//
//
//        // 配置第 3 个数据源 dn3:3308 -> test,test2,test3
//        HikariDataSource dataSource3 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave1_test : 118.31.13.167:3308/test");
//                return super.getConnection();
//            }
//        };
//        dataSource3.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource3.setJdbcUrl("jdbc:mysql://118.31.13.167:3308/test?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource3.setUsername("root");
//        dataSource3.setPassword("root");
//        dataSourceMap.put("slave1_test", dataSource3);
//
//        HikariDataSource dataSource3_1 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave1_test2 : 118.31.13.167:3308/test2");
//                return super.getConnection();
//            }
//        };
//        dataSource3_1.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource3_1.setJdbcUrl("jdbc:mysql://118.31.13.167:3308/test2?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource3_1.setUsername("root");
//        dataSource3_1.setPassword("root");
//        dataSourceMap.put("slave1_test2", dataSource3_1);
//
//        HikariDataSource dataSource3_2 = new HikariDataSource(){
//            @Override
//            public Connection getConnection() throws SQLException {
//                System.out.println("读操作 slave1_test3 : 118.31.13.167:3308/test3");
//                return super.getConnection();
//            }
//        };
//        dataSource3_2.setDriverClassName("com.mysql.cj.jdbc.Driver");
//        dataSource3_2.setJdbcUrl("jdbc:mysql://118.31.13.167:3308/test3?userSSL=true&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT");
//        dataSource3_2.setUsername("root");
//        dataSource3_2.setPassword("root");
//        dataSourceMap.put("slave1_test3", dataSource3_2);
//
//        return dataSourceMap;
//    }
//
//
//    @Bean("dataSource")
//    public DataSource dataSource() throws SQLException {
//        /*数据库*/
//        Map<String, DataSource> dataSourceMap = dataSourceMap();
//
//        // 配置 逻辑表【test_order -> test_order_*】 表规则
//        ShardingTableRuleConfiguration orderTableRuleConfig =
//                new ShardingTableRuleConfiguration("test_order", "dn${0..2}.test_order_${0..1}");
//        orderTableRuleConfig.setDatabaseShardingStrategy(
//                new StandardShardingStrategyConfiguration("uid", "dbRule:test_order_*@[uid]")
//        );
//        orderTableRuleConfig.setTableShardingStrategy(
//                new StandardShardingStrategyConfiguration("order_id", "tableRule:test_order_*@[order_id]")
//        );
//        orderTableRuleConfig.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("cls_desc","keyGeneric:test_order_*@[cls_desc]"));
//
//
//        // 配置 order_item 表规则
//        ShardingTableRuleConfiguration orderItemRuleConfig =
//                new ShardingTableRuleConfiguration("order_item","dn${0..2}.order_item_${0..1}");
//        orderItemRuleConfig.setDatabaseShardingStrategy(
//                new StandardShardingStrategyConfiguration("uid","dbRule:order_item_*@[uid]")
//        );
//        orderItemRuleConfig.setTableShardingStrategy(
//                new StandardShardingStrategyConfiguration("order_id","tableRule:order_item_*@[order_id]")
//        );
//
//        // volume_range 路由规则.
//        ShardingTableRuleConfiguration volumeRangeRuleConfig =
//                new ShardingTableRuleConfiguration("volume_range","dn${0..2}.volume_range_${0..1}");
//        volumeRangeRuleConfig.setDatabaseShardingStrategy(
//                new StandardShardingStrategyConfiguration("id","dbRule:volume_range_*@[id]")
//        );
//        volumeRangeRuleConfig.setTableShardingStrategy(
//                new StandardShardingStrategyConfiguration("range_key","tableRule:volume_range_*@[range_key]")
//        );
//        volumeRangeRuleConfig.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("sknow_flake","keyGeneric:volume_range_*@[sknow_flake]"));
//
//        // hint_tab 路由规则
//        ShardingTableRuleConfiguration hintTabRuleConfig =
//                new ShardingTableRuleConfiguration("hint_tab","dn${0..2}.hint_tab_${0..1}");
//        hintTabRuleConfig.setDatabaseShardingStrategy(new HintShardingStrategyConfiguration("dbRule:hint_tab_*@[*]"));
//        hintTabRuleConfig.setTableShardingStrategy(new HintShardingStrategyConfiguration("tableRule:hint_tab_*@[*]"));
//        hintTabRuleConfig.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("hint_key","keyGeneric:hint_tab_*@[hint_key]"));
//
//        // 配置所有数据库表 的 分片路由规则.
//        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
//        shardingRuleConfig.getTables().add(orderTableRuleConfig);
//        shardingRuleConfig.getTables().add(orderItemRuleConfig);
//        shardingRuleConfig.getTables().add(volumeRangeRuleConfig);
//        shardingRuleConfig.getTables().add(hintTabRuleConfig);
//
//        /*配置所有数据库表的 分片算法 合集.*/
//        //test_order 数据库路由 与 表路由。数据库 uid % 3 , 表 order_id % 2 (test_order 表 只有 0,1)
//        shardingRuleConfig.getShardingAlgorithms().put("dbRule:test_order_*@[uid]",new ShardingSphereAlgorithmConfiguration("MOD", new Properties(){{
//            setProperty("sharding-count", "3");
//        }}));
//        shardingRuleConfig.getShardingAlgorithms().put("tableRule:test_order_*@[order_id]",new ShardingSphereAlgorithmConfiguration("MOD", new Properties(){{
//            setProperty("sharding-count", "2");
//        }}));
//
//        //order_item 数据库路由 与 表路由，数据库保持跟 test_order一致(订单详情所落数据库一定是订单落下的数据库)，表 order_item_id % 3 因为order_item 数据量大，存在3张分片表, 表路由为聚合策略 uid, order_item_id
//        shardingRuleConfig.getShardingAlgorithms().put("dbRule:order_item_*@[uid]",new ShardingSphereAlgorithmConfiguration("INLINE", new Properties(){{
//            setProperty("algorithm-expression", "dn${uid % 3}");
//        }}));
//        shardingRuleConfig.getShardingAlgorithms().put("tableRule:order_item_*@[order_id]",new ShardingSphereAlgorithmConfiguration("MOD", new Properties(){{
//            setProperty("sharding-count", "2");
//        }}));
//
//        // volume_range 路由到数据库 0,1 上
//        shardingRuleConfig.getShardingAlgorithms().put("dbRule:volume_range_*@[id]",new ShardingSphereAlgorithmConfiguration("STANDARD_EL_PARSER", new Properties(){{
//            setProperty("el-expression", " #id % 3");
//            //setProperty("monotonicity", "++");  无单调性.
//        }}));
//        shardingRuleConfig.getShardingAlgorithms().put("tableRule:volume_range_*@[range_key]",new ShardingSphereAlgorithmConfiguration("STANDARD_EL_PARSER", new Properties(){{
//            setProperty("el-expression", " #range_key <= 10 ? 0 : 1");
//            setProperty("monotonicity", "++");  //表路由具备单调性 ++
//        }}));
//
//        // hint_tab 路由算法
//        shardingRuleConfig.getShardingAlgorithms().put("dbRule:hint_tab_*@[*]",new ShardingSphereAlgorithmConfiguration("HINT_EL_PARSER",new Properties(){{
//            setProperty("db","db");
//        }}));
//        shardingRuleConfig.getShardingAlgorithms().put("tableRule:hint_tab_*@[*]",new ShardingSphereAlgorithmConfiguration("HINT_EL_PARSER",new Properties(){{
//            setProperty("tab","tab");
//        }}));
//
//
//
//        /*key生成算法*/
//        KeyGenerateStrategyConfiguration defaultKeyGenerateStrategy = shardingRuleConfig.getDefaultKeyGenerateStrategy();
//        shardingRuleConfig.getKeyGenerators().put("keyGeneric:hint_tab_*@[hint_key]",new ShardingSphereAlgorithmConfiguration("SNOWFLAKE",new Properties(){{
//            setProperty("worker-id","0");
//        }}));
//        shardingRuleConfig.getKeyGenerators().put("keyGeneric:test_order_*@[cls_desc]",new ShardingSphereAlgorithmConfiguration("UUID",new Properties(){{
//            setProperty("casue","uuid");
//        }}));
//        Function<UUID,String> x_uuid_processor = (uuid) -> {
//            return uuid.toString().toUpperCase();
//        };
//        shardingRuleConfig.getKeyGenerators().put("keyGeneric:volume_range_*@[sknow_flake]",new ShardingSphereAlgorithmConfiguration("X_UUID",new Properties(){{
//            put("processor",x_uuid_processor);
//        }}));
//
//        /*配置所有数据库表 的分片绑定, 在开发中不一般不建议绑定表，经测试，表一旦绑定后路由大概率可能出现问题，
//        例如left join联查，主表路由到dn1.tab1 和 dn1.tab2, 但是关联表的路由可能配置不通，例如订单和详情，
//        详情表的数据量可能为订单表的3-5倍，因此订单分表为dn1-3均分出order_0,order_1,而详情表在dn1-3均分出
//         order_item_0,order_item_1,order_item_2，路由配置不同，一旦绑定了订单和详情的逻辑表，而在关联查询时，
//         库表的路由均按照主表(order_*)来，例如dn1.order_1 left join dn1.order_item_1, 而忽略了order_item_0以及order_item_1
//         ，因此在数据分片规则不同时，使用逻辑关联，智能满足很小一部分查询逻辑(大多数情况下会由于路由配置的差异导致查询错误或者不完整)，
//         因此，慎用！,或者使用HintManager去强制控制路由~*/
//        //shardingRuleConfig.getBindingTableGroups().add("test_order,order_item");
//
//        //系统配置
//        Properties globalProps = new Properties();
//        globalProps.setProperty("sql-show","true");
//
//        //主从配置.
//        RuleConfiguration masterSlaveConfig = getMasterSlaveConfig();
//
//        DataSource dataSource = ShardingSphereDataSourceFactory.createDataSource(
//                dataSourceMap,
//                Arrays.asList(shardingRuleConfig,masterSlaveConfig),
//                globalProps
//        );
//        return dataSource;
//    }
//
//    /**
//     * 主从配置组
//     * @return
//     */
//    private RuleConfiguration getMasterSlaveConfig(){
//        // 主从组one，主数据节点 dn1, 从数据节点dn2,dn3, 负载算法:MasterSlaveBalancer::ROUND_ROBIN
//        ReplicaQueryDataSourceRuleConfiguration masterSlaveGroupTest = new ReplicaQueryDataSourceRuleConfiguration(
//                "MasterSlaveGroup1@test",
//                "dn0",
//                Arrays.asList("slave0_test","slave1_test"),
//                "MasterSlaveBalancer::ROUND_ROBIN"
//        );
//
//        ReplicaQueryDataSourceRuleConfiguration masterSlaveGroupTest2 = new ReplicaQueryDataSourceRuleConfiguration(
//                "MasterSlaveGroup2@test2",
//                "dn1",
//                Arrays.asList("slave0_test2","slave1_test2"),
//                "MasterSlaveBalancer::ROUND_ROBIN"
//        );
//
//        ReplicaQueryDataSourceRuleConfiguration masterSlaveGroupTest3 = new ReplicaQueryDataSourceRuleConfiguration(
//                "MasterSlaveGroup3@test3",
//                "dn2",
//                Arrays.asList("slave0_test3","slave1_test3"),
//                "MasterSlaveBalancer::ROUND_ROBIN"
//        );
//
//        ReplicaQueryRuleConfiguration masterSlavesConfigs = new ReplicaQueryRuleConfiguration(
//                Arrays.asList(masterSlaveGroupTest,masterSlaveGroupTest2,masterSlaveGroupTest3),
//                new HashMap<String, ShardingSphereAlgorithmConfiguration>(){{
//                    put(
//                            "MasterSlaveBalancer::ROUND_ROBIN",
//                            new ShardingSphereAlgorithmConfiguration("ROUND_ROBIN",new Properties())
//                    );
//                }}
//        );
//
//        return masterSlavesConfigs;
//    }
//
//    @Bean("sqlSessionFactory")
//    public SqlSessionFactory sqlSessionFactory(final DataSource dataSource) throws Exception {
//        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//        sqlSessionFactoryBean.setDataSource(dataSource);
//        return sqlSessionFactoryBean.getObject();
//    }
//
//}
